
package com.schedualnew.mq.util;
//import com.rt.schedulebase.dto.NoticeDto;
//import com.rt.util.JsonUtil;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;

import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class XmlUtil {
    public static String object2xmlResponse(String resultName, Object obj, String status, String msg) {
        Map<String, Object> map = new HashMap<String, Object>();
        Map<String, Object> resultMap = new HashMap<String, Object>();
        Map<String, Object> responseMap = new HashMap<String, Object>();
        resultMap.put("code", "1".equals(status) ? "-1" : status);
        resultMap.put("desc", msg);
        if (obj != null) {
            if (obj instanceof List) {
                List<Object> objectList = new ArrayList<Object>();
                for (Object beanObj : (List) obj) {
                    if (beanObj instanceof Map) {
                        Map<String, Object> beanMap = (Map<String, Object>) beanObj;
                        for (String key : beanMap.keySet()) {
                            if (!(beanMap.get(key) instanceof String) && !isBaseType(beanMap.get(key))) {
                                Map<String, Object> objectMap = object2map(beanMap.get(key));
                                beanMap.put(key, objectMap);
                            }
                        }
                        objectList.add(beanMap);
                    } else if (beanObj instanceof String || isBaseType(beanObj)) {
                        objectList.add(beanObj);
                    } else {
                        Map<String, Object> objectMap2 = object2map(beanObj);
                        objectList.add(objectMap2);
                    }
                }
                map.put(resultName, objectList);
                if (resultName.endsWith("ss")) {
                    resultMap.put(resultName + "es", map);
                } else {
                    resultMap.put(resultName + "s", map);
                }
            } else if (obj instanceof Map) {
                resultMap.put(resultName, obj);
            } else {
                Map<String, Object> objectMap3 = object2map(obj);
                resultMap.put(resultName, objectMap3);
            }
        }
        responseMap.put("Response", resultMap);
        String jsonResult = JSON.toJSONString(responseMap)
                .replace("&lt;", "<")
                .replace("&gt;", ">");
        String xmlResponse = CommonUtil.json2Xml(jsonResult);
        if (StringUtils.isBlank(resultName)) {
            xmlResponse = CommonUtil.json2Xml(jsonResult).replace("<null>", "").replace("</null>", "");
            xmlResponse = xmlResponse.replace("<nulls>", "").replace("</nulls>", "");
        }
        return xmlResponse;
    }

    public static String object2xmlResponse(Object obj, String status, String msg) {
        return object2xmlResponse(null, obj, status, msg);
    }

    public static String object2xmlResponse(String status, String msg) {
        return object2xmlResponse(null, null, status, msg);
    }

    /**
     * 将xml转成java 对象实体
     * @param req
     * @param beanClass
     * @param values
     * @return
     * @param <T>
     */
    public static <T> T xmlRequest2Bean(String req, Class<T> beanClass, String values) {
        req = req.replace("<Header>", "").replace("</Header>", "");
        Map<String, Object> map = new HashMap<>();
        // 将请求结构转成json node
        JSONObject xmlJsonObject = xml2JSON(req);

        List<String> valueList = CommonUtil.split2List(values);
        valueList.forEach(value -> map.put(value, xmlJsonObject.getString(value)));
        String beanJson = JSON.toJSONString(map);
        try {
            T bean = JSON.parseObject(beanJson, beanClass);
            return bean;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 将xml字符串转成json 对象
     * @param xmlStr
     * @return
     */
    public static JSONObject xml2JSON(String xmlStr) {
        SAXBuilder saxBuilder = new SAXBuilder();
        ByteArrayInputStream tInputStringStream = new ByteArrayInputStream(xmlStr.getBytes());
        InputStreamReader isr = new InputStreamReader(tInputStringStream);
        try {
            Document document = saxBuilder.build(isr);
            Element rootElement = document.getRootElement();
            JSONObject jsonObject = new JSONObject();
            xml2Json(rootElement, jsonObject);
            return jsonObject;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static void xml2Json(Element element, JSONObject jsonObject) {
        List<Element> childElements = element.getChildren();
        if (childElements.isEmpty()) {
            analyticElement(element, jsonObject);
        } else {
            for (Element node : childElements) {
                if (node.getChildren() != null && !node.getChildren().isEmpty()) {
                    JSONObject childJsonObject = new JSONObject();
                    xml2Json(node, childJsonObject);
                    Object object = jsonObject.get(node.getName());
                    if (object != null) {
                        JSONArray jsonArray = null;
                        if (object instanceof JSONObject) {
                            JSONObject jsono = (JSONObject) object;
                            jsonObject.remove(node.getName());
                            jsonArray = new JSONArray();
                            jsonArray.add(jsono);
                            jsonArray.add(childJsonObject);
                        }
                        if (object instanceof JSONArray) {
                            jsonArray = (JSONArray) object;
                            jsonArray.add(childJsonObject);
                        }
                        jsonObject.put(node.getName(), jsonArray);
                    } else {
                        if (childJsonObject.isEmpty()) {
                            continue;
                        }
                        jsonObject.put(node.getName(), childJsonObject);
                    }
                } else {
                    analyticElement(node, jsonObject);
                }
            }
        }
    }

    private static void analyticElement(Element element, JSONObject jsonObject) {
        List<Attribute> attributeList = element.getAttributes();
        if (attributeList != null && !attributeList.isEmpty()) {
            JSONObject attrObject = new JSONObject();
            for (Attribute attr : attributeList) {
                attrObject.put(attr.getName(), attr.getValue());
            }
            attrObject.put("value", element.getValue());
            jsonObject.put(element.getName(), attrObject);
        } else {
            jsonObject.put(element.getName(), element.getValue());
        }
    }

    private static Map<String, Object> object2map(Object obj) {
        Class c = obj.getClass();
        Map<String, Object> map = new HashMap<>();
        objectToMap(c, obj, map);
        c = c.getSuperclass();
        objectToMap(c, obj, map);
        return map;
    }

    private static void objectToMap(Class c, Object obj, Map<String, Object> resultMap) {
        try {
            Field[] declaredFields;
            Field[] fields = declaredFields = c.getDeclaredFields();
            for (Field f : declaredFields) {
                f.setAccessible(true);
                if (f.get(obj) != null && !isAllUpperCase(f.getName()) && !f.getName().equals("serialVersionUID")) {
                    if (f.getType().toString().contains("java.util.List")) {
                        if (f.getName().substring(f.getName().length() - 1).equals("s")) {
                            Map<String, Object> fMap = new HashMap<String, Object>();
                            ArrayList fList = (ArrayList) (f.get(obj));
                            fMap.put(f.getName().substring(0, f.getName().length() - 1), fList);
                            resultMap.put(f.getName(), fMap);
                        } else if (f.getName().substring(f.getName().length() - 4).equals("List")) {
                            Map<String, Object> fMap = new HashMap<String, Object>();
                            ArrayList fList = (ArrayList) (f.get(obj));
                            fMap.put(f.getName().substring(0, f.getName().length() - 4), fList);
                            resultMap.put(f.getName(), fMap);
                        } else {
                            Map<String, Object> listMap = new HashMap<String, Object>();
                            listMap.put(f.getName(), f.get(obj));
                            resultMap.put(f.getName() + "s", listMap);
                        }
                    } else {
                        resultMap.put(f.getName(), f.get(obj));
                    }
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String object2xmlResponse_V2(String resultName, Object obj, String status, String msg) {
        Map<String, Object> responseMap = new HashMap<String, Object>();
        Map<String, Object> map = new HashMap<String, Object>();
        Map<String, Object> resultMap = new HashMap<String, Object>();
        if (obj != null) {
            objToMap_V2(obj, map, resultName);
            if (obj instanceof List) {
                resultMap.putAll(map);
            } else {
                resultMap.put(resultName, map);
            }
        }
        resultMap.put("code", "1".equals(status) ? "-1" : status);
        resultMap.put("desc", msg);
        responseMap.put("Response", resultMap);
        String jsonResult = JSON.toJSONString((Object) responseMap).replace("&lt;", "<").replace("&gt;", ">");
        String xmlResponse = CommonUtil.json2Xml(jsonResult);
        if (StringUtils.isBlank(resultName)) {
            xmlResponse = CommonUtil.json2Xml(jsonResult).replace("<null>", "").replace("</null>", "");
            xmlResponse = xmlResponse.replace("<nulls>", "").replace("</nulls>", "");
        }
        return xmlResponse;
    }

    public static String object2xmlResponse_V2(Object obj, String status, String msg) {
        return object2xmlResponse_V2(null, obj, status, msg);
    }

    public static String object2xmlResponse_V2(String status, String msg) {
        return object2xmlResponse_V2(null, null, status, msg);
    }

    private static void objToMap_V2(Object obj, Map<String, Object> resultMap, String key) {
        if (obj instanceof String || isBaseType(obj)) {
            resultMap.put(key, obj);
        } else if (obj instanceof List) {
            List<Object> tempList = new ArrayList<Object>();
            Map<String, Object> resultBeforeList = new HashMap<String, Object>(resultMap);
            resultMap.clear();
            for (Object o : (List) obj) {
                objToMap_V2(o, resultMap, "strKey");
                Map<String, Object> tempMap = new HashMap<String, Object>(resultMap);
                if (tempMap.get("strKey") != null) {
                    tempList.add(tempMap.get("strKey"));
                } else {
                    tempList.add(tempMap);
                }
                resultMap.clear();
            }
            Map<String, Object> tempMap2 = new HashMap<String, Object>();
            tempMap2.put(key, tempList);
            if (key.substring(key.length() - 1).equals("s")) {
                resultMap.put(key + "es", tempList);
            } else {
                resultMap.put(key + "s", tempMap2);
            }
            resultMap.putAll(resultBeforeList);
        } else if (obj instanceof Map) {
            Map<String, Object> map = (Map<String, Object>) obj;
            for (String mapKey : map.keySet()) {
                objToMap_V2(map.get(mapKey), resultMap, mapKey);
            }
        } else {
            try {
                Class c = obj.getClass();
                Field[] declaredFields;
                Field[] fields = declaredFields = c.getDeclaredFields();
                for (Field f : declaredFields) {
                    f.setAccessible(true);
                    if (f.get(obj) != null && !isAllUpperCase(f.getName()) && !f.getName().equals("serialVersionUID")) {
                        objToMap_V2(f.get(obj), resultMap, f.getName());
                    }
                }
                c = c.getSuperclass();
                Field[] declaredFields2;
                Field[] superFields = declaredFields2 = c.getDeclaredFields();
                for (Field f2 : declaredFields2) {
                    f2.setAccessible(true);
                    if (f2.get(obj) != null && !isAllUpperCase(f2.getName()) && !f2.getName().equals("serialVersionUID")) {
                        Map<String, Object> map2 = new HashMap<String, Object>();
                        objToMap_V2(f2.get(obj), resultMap, f2.getName());
                    }
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }

    private static boolean isBaseType(Object obj) {
        Class className = obj.getClass();
        return className.equals(Integer.class) || className.equals(Byte.class) || className.equals(Long.class) || className.equals(Double.class) || className.equals(Float.class) || className.equals(Character.class) || className.equals(Short.class) || className.equals(Boolean.class);
    }

    private static boolean isAllUpperCase(String word) {
        for (int i = 0; i < word.length(); ++i) {
            char c = word.charAt(i);
            if (Character.isLowerCase(c)) {
                return false;
            }
        }
        return true;
    }

    public static void main(String[] args) {
        String noticeStr = "<notices>\n    <notice>\n        <minDays>1</minDays>\n        <maxDays>365</maxDays>\n        <patientSource>门诊</patientSource>\n        <text>1岁注意事项</text>\n    </notice>\n    <notice>\n        <minDays>366</minDays>\n        <maxDays>800</maxDays>\n        <patientSource>住院</patientSource>\n        <text>2岁注意事项</text>\n    </notice>\n</notices>";
        int ageDays = DateUtils.getBirthDays("1992-10-15");
        System.out.println(ageDays);
        JSONObject jsonObject = xml2JSON(noticeStr);
        List<String> jsonNotice = CommonUtil.getJsonNode(jsonObject.toJSONString(), "$.notice");
        for (String s : jsonNotice) {
            Map<String, Object> map = (Map<String, Object>) JsonUtil.json2Map(s);
            int minDays = Integer.valueOf(map.get("minDays").toString());
            int maxDays = Integer.valueOf(map.get("maxDays").toString());
            String text = map.get("text").toString();
            if (ageDays >= minDays && ageDays <= maxDays) {
                noticeStr = text;
                System.out.println(noticeStr);
                break;
            }
        }
    }

    public static String objectToXml(Object obj, String rootTagStart, String rootTagEnd) {
        Class<?> aClass = obj.getClass();
        Field[] declaredFields = aClass.getDeclaredFields();
        StringBuilder builder = new StringBuilder();
        builder.append(rootTagStart);
        for (Field field : declaredFields) {
            field.setAccessible(true);
            String name = field.getName();
            String value = "";
            try {
                value = String.valueOf(field.get(obj));
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            if (StringUtils.isNotBlank(value)) {
                String tagStart = "<" + name + ">";
                String tagEnd = "</" + name + ">";
                if (!name.equals("sortNo")) {
                    if (name.equals("taboo")) {
                        value = value.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
                    }
                    builder.append(tagStart).append(value).append(tagEnd);
                }
            }
        }
        builder.append(rootTagEnd);
        return builder.toString();
    }

    public static String mapToXml(Map<String, Object> map, String rootTagStart, String rootTagEnd, String tagStart, String tagEnd) {
        if (map == null || map.size() == 0) {
            return "";
        }
        int size = map.size();
        StringBuilder builder = new StringBuilder();
        builder.append(rootTagStart);
        for (int i = 0; i < size; ++i) {
            String key = i + "";
            Object obj = map.get(key);
            if (obj != null) {
                String toXml = objectToXml(obj, tagStart, tagEnd);
                builder.append(toXml);
            }
        }
        builder.append(rootTagEnd);
        return builder.toString();
    }
}
